package com.kellycheung.chicken_go_go;

import java.util.Collections;

import org.json.JSONObject;

import com.kellycheung.chicken_go_go.BaseObject.GOAnchor;
import com.kellycheung.chicken_go_go.Chicken.ChickenStatus;
import com.kellycheung.chicken_go_go.ScrollableObj.ScrollDirection;
import com.kellycheung.chicken_go_go.TimerObj.TimerType;

import android.graphics.Color;

public class GameRacing extends GameScene {
	protected static final int I_EXTRA_CNT = 46;
	
	protected ScrollableObj soBackGround;
	protected Chicken chicken;
	protected ClickableObj coRunBtn;
	protected ClickableObj coJumpBtn;
	protected TimerObj toTimer;
	protected TimerObj toStartTimer;
	protected PlayerStatusObj psoStatus;
	protected GOObstacleHandler gooHandler;
	protected int[] iImgBg;
	protected GRectangle grDrawScene;
	protected GMenu gmPauseMenu;
	protected GMenu gmLossMenu;
	protected GMenu gmWinMenu;
	protected GMenu gmConfirmExitMenu;
	protected GMenu gmConfirmBackMenu;
	
	protected float fProgressTtl;
	protected int iPlayerIdx;
	protected String sPlayerName;
	protected float fGroundLv;
	protected int iTime;
	protected float fLastDisp;
	protected boolean raceNotStart = true;
	protected int iStage;
	protected int iCoins;
	
	public GameRacing( GameEngine p_geMain , String[] p_sParm ) {
		super( p_geMain , GameRacing.I_EXTRA_CNT , p_sParm );
		// TODO Auto-generated constructor stub
		
		try {
			this.iLoadCnt++;
			
			this.initGRVar( Integer.valueOf( this.sParm[0] ) );
			
			// Background
			this.soBackGround = new ScrollableObj( this , 0 );
			this.soBackGround.addAnimation( this.iImgBg );
			this.soBackGround.setDirection( ScrollDirection.horizontal );
			this.addBackGround( soBackGround );
			this.iLoadCnt++;
			
			// Chicken
	        this.chicken = new Chicken( this , 10 );
	        this.chicken.addAnimation( ChickenStatus.normal , new int[]{ R.drawable.chicken_walk_04 } );
	        this.chicken.addAnimation( ChickenStatus.run , new int[]{ R.drawable.chicken_walk_01 , R.drawable.chicken_walk_02 , R.drawable.chicken_walk_03 , R.drawable.chicken_walk_04 } , 6 );
	        this.chicken.addAnimation( ChickenStatus.jump , new int[]{ R.drawable.chicken_fly_01 , R.drawable.chicken_fly_02 } , 6);
	        this.chicken.addAnimation( ChickenStatus.collided , new int[]{ R.drawable.chicken_hit , 0 } , 6 );
	        this.chicken.gssAllowStatus = GameSceneStatus.grNormal;
	        this.chicken.grBound.set( this.chicken.grBound.scale( 0.15f , 0.3f , GOAnchor.DownRight ).scale( 0.15f , 0.2f, GOAnchor.UpLeft ) );
	        this.chicken.setCoord( 400f , this.fGroundLv );
	        this.chicken.setMovement();
	        this.chicken.iAllowJumpCnt = 2;
	        this.addSceneObj( this.chicken );
	        this.iLoadCnt++;
	        
	        // Run Button
	        this.coRunBtn = new ClickableObj( this , 0 , GOAnchor.DownLeft , 0f , p_geMain.gcScreenSize.fY );
	        this.coRunBtn.addAnimation( new int[]{ R.drawable.btn_right } );
	        this.coRunBtn.gssAllowStatus = GameSceneStatus.grNormal;
	        this.coRunBtn.setBtnPressAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					// TODO Auto-generated method stub
					chickenMove( true );
					
					return null;
				}
	        });
	        this.coRunBtn.setBtnReleaseAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					// TODO Auto-generated method stub
					chickenMove( false );
					
					return null;
				}
	        });
	        this.addSceneObj( this.coRunBtn );
	        this.addClickableObj( this.coRunBtn );
	        this.iLoadCnt++;
	        
	        // Jump Button
	        this.coJumpBtn = new ClickableObj( this , 0 , GOAnchor.DownRight , p_geMain.gcScreenSize.fX , p_geMain.gcScreenSize.fY );
	        this.coJumpBtn.iAllowClick = 2;
	        this.coJumpBtn.addAnimation( new int[]{ R.drawable.btn_up } );
	        this.coJumpBtn.gssAllowStatus = GameSceneStatus.grNormal;
	        this.coJumpBtn.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					// TODO Auto-generated method stub
					chickenJump();
					
					return null;
				}
	        } , false );
	        this.coJumpBtn.setBtnPressAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					// TODO Auto-generated method stub
					chickenJumpHigher();
					
					return null;
				}
	        });
	        this.addSceneObj( this.coJumpBtn );
	        this.addClickableObj( this.coJumpBtn );
	        this.iLoadCnt++;
	        
	        // Pause Button
	        ClickableObj pauseBtn = new ClickableObj( this , 0 , GOAnchor.UpRight , p_geMain.gcScreenSize.fX , 0f );
	        pauseBtn.addAnimation( new int[]{ R.drawable.btn_pause } );
	        pauseBtn.gssAllowStatus = GameSceneStatus.grNormal;
	        pauseBtn.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					// TODO Auto-generated method stub
					pause();
					
					return null;
				}
	        } );
	        this.addSceneObj( pauseBtn );
	        this.addClickableObj( pauseBtn );
	        this.iLoadCnt++;
	        
	        // Timer
	        this.toTimer = new TimerObj( this , 0 , TimerType.countDown , this.iTime , GOAnchor.Up , ((float)this.geMain.gcScreenSize.fX)/2f , 0f);
	        this.toTimer.addAnimation( new int[]{ R.drawable.txt_0 , R.drawable.txt_1 , R.drawable.txt_2 , R.drawable.txt_3 , R.drawable.txt_4 , R.drawable.txt_5 , R.drawable.txt_6 , R.drawable.txt_7 , R.drawable.txt_8 , R.drawable.txt_9 } );
	        this.toTimer.gssAllowStatus = GameSceneStatus.grNormal;
	        this.toTimer.setAnimation();
	        this.addSceneObj( toTimer );
	        this.iLoadCnt++;
	        
	        toStartTimer = new TimerObj( this , 0 , TimerType.countDown , 3 , GOAnchor.Center , ((float)this.geMain.gcScreenSize.fX)/2f , ((float)this.geMain.gcScreenSize.fY)/2f);
	        toStartTimer.addAnimation( new int[]{ R.drawable.txt_0 , R.drawable.txt_1 , R.drawable.txt_2 , R.drawable.txt_3 , R.drawable.txt_4 , R.drawable.txt_5 , R.drawable.txt_6 , R.drawable.txt_7 , R.drawable.txt_8 , R.drawable.txt_9 } );
	        toStartTimer.gssAllowStatus = GameSceneStatus.grWaiting;
	        toStartTimer.setAnimation();
	        this.addSceneObj( toStartTimer );
	        this.iLoadCnt++;
	
	        GameObject iconClock = new GameObject( this , 0 , GOAnchor.UpRight , ((float)this.geMain.gcScreenSize.fX)/2f - this.toTimer.getTimerWidth()/2f - (20f*this.geMain.gcScreenSize.fX/1918f) , 0f );
	        iconClock.addAnimation( new int[]{ R.drawable.icon_clock } );
	        iconClock.gssAllowStatus = GameSceneStatus.grNormal;
	
	        this.addSceneObj( iconClock );
	        this.iLoadCnt++;
	        
	        // Progress Bar
	        float fW = this.geMain.gcScreenSize.fX*0.6f;
	        float fH = this.geMain.gcScreenSize.fY*0.2f;
	        this.psoStatus = new PlayerStatusObj( this , 0 , GOAnchor.Up , (this.geMain.gcScreenSize.fX)/2f , (this.geMain.gcScreenSize.fY - fH) , fW , fH , 10f );
	        this.psoStatus.gssAllowStatus = GameSceneStatus.grNormal;
	        this.sPlayerName = "P1";
	        this.iPlayerIdx = this.psoStatus.addPlayer( this.sPlayerName , this.fProgressTtl );
	        this.addSceneObj( this.psoStatus );
	        this.iLoadCnt++;
	        
	        this.grDrawScene = new GRectangle( this.geMain.gcScreenSize.fX , 0f , 0f , this.geMain.gcScreenSize.fY );
	        
	        this.initPauseMenu();
	        this.initWinMenu();
	        this.initLossMenu();
	        this.initConfirmExitMenu();
	        this.initConfirmBackMenu();
	        
	        Collections.sort( this.alboBackGround );
	        Collections.sort( this.alboSceneObj );
	        Collections.sort( this.alboForeGround );
	        Collections.sort( this.alcoClickableObj );
	        this.iLoadCnt++;
	        
	        this.gssStatus = GameSceneStatus.grWaiting;
			this.gssStatusNormal = GameSceneStatus.grNormal;
			
			this.iCoins = 0;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void destroy() {
		try {
			if ( this.soBackGround != null ) {
				this.soBackGround.destroy();
				this.soBackGround = null;
			}
			
			if ( this.chicken != null ) {
				this.chicken.destroy();
				this.chicken = null;
			}
			
			if ( this.coRunBtn != null ) {
				this.coRunBtn.destroy();
				this.coRunBtn = null;
			}
			
			if ( this.coJumpBtn != null ) {
				this.coJumpBtn.destroy();
				this.coJumpBtn = null;
			}
			
			if ( this.toTimer != null ) {
				this.toTimer.destroy();
				this.toTimer = null;
			}
			
			if ( this.toStartTimer != null ) {
				this.toStartTimer.destroy();
				this.toStartTimer = null;
			}
			
			if ( this.psoStatus != null ) {
				this.psoStatus.destroy();
				this.psoStatus = null;
			}
			
			if ( this.gooHandler != null ) {
				this.gooHandler.destroy();
				this.gooHandler = null;
			}
			
			if ( this.iImgBg != null ) {
				this.iImgBg = null;
			}
			
			if ( this.grDrawScene != null ) {
				this.grDrawScene = null;
			}
			
			if ( this.gmPauseMenu != null ) {
				this.gmPauseMenu.destroy();
				this.gmPauseMenu = null;
			}
			
			if ( this.gmLossMenu != null ) {
				this.gmLossMenu.destroy();
				this.gmLossMenu = null;
			}
			
			if ( this.gmWinMenu != null ) {
				this.gmWinMenu.destroy();
				this.gmWinMenu = null;
			}
			
			if ( this.gmConfirmExitMenu != null ) {
				this.gmConfirmExitMenu.destroy();
				this.gmConfirmExitMenu = null;
			}
			
			if ( this.gmConfirmBackMenu != null ) {
				this.gmConfirmBackMenu.destroy();
				this.gmConfirmBackMenu = null;
			}
			
			super.destroy();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.destroy" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void initVariables() {
		this.iResBGMusic = 0;
	}
	
	public void initGRVar( int p_iStage ) {
		try {
			this.iStage = p_iStage;
			
			this.fGroundLv = 800f;
			this.fLastDisp = 0f;
			
			this.iImgBg = new int[]{ R.drawable.bg };
			
			if ( this.gooHandler != null ) {
				this.gooHandler.destroy();
				this.gooHandler = null;
			}
			
			this.gooHandler = new GOObstacleHandler( this , GameSceneStatus.grNormal );
			GPosition gpBall = new GPosition( 0.0f , 0.0f );
			gpBall.setXAcc( -2.0f , false );
			gpBall.setXSpeedMax( -25.0f );
			
			int iCoinResId = 0;
			if ( this.bIsAnyBTConnectionCreated ) {
				iCoinResId = R.drawable.coin_blue;
			}
			else {
				iCoinResId = R.drawable.coin;
			}
			
			switch ( this.iStage ) {
			case 1:
				this.fProgressTtl = 12000f;
				this.iTime = 60;
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 3000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 5000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 6000f );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 9000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 10000f , 300f , ChickenStatus.getCoin );
				break;
				
			case 2:
				this.fProgressTtl = 15000f;
				this.iTime = 60;
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 3000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 5000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 6000f );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 9000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 10000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 12000f );
				break;
				
			case 3:
				this.fProgressTtl = 15000f;
				this.iTime = 45;
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 3000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 5000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 6000f );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 9000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 10000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 12000f );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 15000f );
				break;
				
			case 4:
				this.fProgressTtl = 20000f;
				this.iTime = 45;
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 3000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 5000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.ball } , 6000f , 400f , gpBall );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 9000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 10000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.ball } , 12000f , 400f , gpBall );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 15000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 15000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.ball } , 18000f , 400f , gpBall );
				break;
			
			default:
				this.fProgressTtl = 20000f;
				this.iTime = 40;
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 3000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 5000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.ball } , 6000f , 400f , gpBall );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 9000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 10000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.ball } , 12000f , 400f , gpBall );
				this.gooHandler.addObstacle( new int[] { R.drawable.tile } , 15000f );
				this.gooHandler.addObstacle( new int[] { iCoinResId } , 15000f , 300f , ChickenStatus.getCoin );
				this.gooHandler.addObstacle( new int[] { R.drawable.ball } , 18000f , 400f , gpBall );
				break;
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.initGRVar" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void chickenMove( boolean p_bIsMove ) {
		try {
			this.chicken.move( p_bIsMove );
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.chickenMove" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}

	public void chickenJump() {
		try {
			this.chicken.jump();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.chickenJump" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void chickenJumpHigher() {
		try {
			this.chicken.jumpHigher();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.chickenJumpHigher" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void pause() {
		try {
			if ( this.joNetwork.length() == 0 ) {
				switch ( this.gssStatus ) {
				case grNormal:
					this.gmPauseMenu.showMenu();
					break;
				case grPause:
					this.gmPauseMenu.hideMenu();
					break;
				default:
					break;
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.pause" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void confirmExit() {
		try {
			switch ( this.gssStatus ) {
			case grPause:
				this.gmConfirmExitMenu.showMenu();
				break;
			case grConfirmExit:
				this.gmConfirmExitMenu.hideMenu();
				break;
			default:
				break;	
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.confirmExit" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void confirmBackMenu() {
		try {
			switch ( this.gssStatus ) {
			case grPause:
				this.gmConfirmBackMenu.showMenu();
				break;
			case grConfirmBack:
				this.gmConfirmBackMenu.hideMenu();
				break;
			default:
				break;	
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.confirmBackMenu" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void initPauseMenu() {
		try {
			// Pause Menu
			this.gmPauseMenu = new GMenu( this , 0f , 0f , this.geMain.gcScreenSize.fX , this.geMain.gcScreenSize.fY , 3 , GameSceneStatus.grPause );
			this.iLoadCnt++;
			
	        GeometryObj goPauseAlphaBg = new GeometryObj( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
	        goPauseAlphaBg.setGeometry( new GRectangle( this.geMain.gcScreenSize.fX , 0f , 0f , this.geMain.gcScreenSize.fY ) , Color.rgb(255,255,255) , 127 );
	        this.gmPauseMenu.addMenuBg( goPauseAlphaBg );
	        this.iLoadCnt++;
	        
			GameObject goPauseGrey = new GameObject( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
			goPauseGrey.addAnimation( new int[]{ R.drawable.background_grey } );
			this.gmPauseMenu.addMenuBg( goPauseGrey );
			this.gmPauseMenu.grBound.set( goPauseGrey.grBound.scale( 1.0f , 0.8f , GOAnchor.Center ) );
			this.iLoadCnt++;
			
			this.gmPauseMenu.addNewMenuRow( 1 );
	        ClickableObj coPauseResume = new ClickableObj( this , 0 , GOAnchor.Center );
	        coPauseResume.addAnimation( new int[]{ R.drawable.btn_resume_game } );
	        coPauseResume.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					pause();
					return null;
				}
	        } );
	        this.gmPauseMenu.addMenuItem( coPauseResume );
	        this.iLoadCnt++;
	        
			this.gmPauseMenu.addNewMenuRow( 1 );
	        ClickableObj coPauseHome = new ClickableObj( this , 0 , GOAnchor.Center );
	        coPauseHome.addAnimation( new int[]{ R.drawable.btn_menu } );
	        coPauseHome.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					confirmBackMenu();
	
					return null;
				}
	        } );
	        this.gmPauseMenu.addMenuItem( coPauseHome );
	        this.iLoadCnt++;
	        
			this.gmPauseMenu.addNewMenuRow( 1 );
	        ClickableObj coPauseExit = new ClickableObj( this , 0 , GOAnchor.Center );
	        coPauseExit.addAnimation( new int[]{ R.drawable.btn_exit_game } );
	        coPauseExit.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					confirmExit();
					//geMain.aApp.finish();
					
					//geMain.isGameEnded = true;
					return null;
				}
	        } );
	        this.gmPauseMenu.addMenuItem( coPauseExit );
	        this.iLoadCnt++;
	        
			this.algmMenuList.add( this.gmPauseMenu );
			this.iLoadCnt++;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.initPauseMenu" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void initWinMenu() {
		try {
			// Win Menu
			this.gmWinMenu = new GMenu( this , 0f , 0f , this.geMain.gcScreenSize.fX , this.geMain.gcScreenSize.fY , 3 , GameSceneStatus.grGameWin );
			this.iLoadCnt++;
			
	        GeometryObj goWinAlphaBg = new GeometryObj( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
	        goWinAlphaBg.setGeometry( new GRectangle( this.geMain.gcScreenSize.fX , 0f , 0f , this.geMain.gcScreenSize.fY ) , Color.rgb(255,255,255) , 127 );
	        this.gmWinMenu.addMenuBg( goWinAlphaBg );
	        this.iLoadCnt++;
	        
			GameObject goWinGrey = new GameObject( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
			goWinGrey.addAnimation( new int[]{ R.drawable.background_grey } );
	        this.gmWinMenu.addMenuBg( goWinGrey );
	        this.gmWinMenu.grBound.set( goWinGrey.grBound );
	        this.iLoadCnt++;
	        
			this.gmWinMenu.addNewMenuRow( 1 );
	        GameObject goWinYeah = new GameObject( this , 0 , GOAnchor.Down );
	        goWinYeah.addAnimation( new int[]{ R.drawable.txt_yeah } );
	        this.gmWinMenu.addMenuItem( goWinYeah );
	        this.iLoadCnt++;
	        
			this.gmWinMenu.addNewMenuRow( 1 );
	        GameObject goWinWin = new GameObject( this , 0 , GOAnchor.Down );
	        goWinWin.addAnimation( new int[]{ R.drawable.txt_win } );
	        this.gmWinMenu.addMenuItem( goWinWin );
	        this.iLoadCnt++;
	        
			this.gmWinMenu.addNewMenuRow( 1 );
	        ClickableObj coWinOK = new ClickableObj( this , 0 , GOAnchor.Center );
	        coWinOK.addAnimation( new int[]{ R.drawable.btn_ok } );
	        this.gmWinMenu.addMenuItem( coWinOK );
	        coWinOK.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					goRewardPage( false );
					return null;
				}
			});
	        this.iLoadCnt++;
	        
			this.algmMenuList.add( this.gmWinMenu );
			this.iLoadCnt++;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.initWinMenu" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void initLossMenu() {
		try {
			// Loss Menu
			this.gmLossMenu = new GMenu( this , 0f , 0f , this.geMain.gcScreenSize.fX , this.geMain.gcScreenSize.fY , 3 , GameSceneStatus.grGameOver );
			this.iLoadCnt++;
			
	        GeometryObj goLossAlphaBg = new GeometryObj( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
	        goLossAlphaBg.setGeometry( new GRectangle( this.geMain.gcScreenSize.fX , 0f , 0f , this.geMain.gcScreenSize.fY ) , Color.rgb(255,255,255) , 127 );
	        this.gmLossMenu.addMenuBg( goLossAlphaBg );
	        this.iLoadCnt++;
	        
			GameObject goLossGrey = new GameObject( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
			goLossGrey.addAnimation( new int[]{ R.drawable.background_grey } );
			this.gmLossMenu.addMenuBg( goLossGrey );
			this.gmLossMenu.grBound.set( goLossGrey.grBound );
			this.iLoadCnt++;
			
			this.gmLossMenu.addNewMenuRow( 1 );
			GameObject goLossTooBad = new GameObject( this , 0 , GOAnchor.Down );
			goLossTooBad.addAnimation( new int[]{ R.drawable.txt_toobad } );
			this.gmLossMenu.addMenuItem( goLossTooBad );
			this.iLoadCnt++;
			
			this.gmLossMenu.addNewMenuRow( 1 );
			GameObject goLossTimeUp = new GameObject( this , 0 , GOAnchor.Down );
			goLossTimeUp.addAnimation( new int[]{ R.drawable.txt_timesup } );
			this.gmLossMenu.addMenuItem( goLossTimeUp );
			this.iLoadCnt++;
			
			this.gmLossMenu.addNewMenuRow( 1 );
			ClickableObj coLossOK = new ClickableObj( this , 0 , GOAnchor.Center );
			coLossOK.addAnimation( new int[]{ R.drawable.btn_ok } );
			this.gmLossMenu.addMenuItem( coLossOK );
			coLossOK.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					goRewardPage( false );
					return null;
				}
			});
			this.iLoadCnt++;
			
			this.algmMenuList.add( this.gmLossMenu );
			this.iLoadCnt++;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.initLossMenu" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void initConfirmExitMenu() {
		try {
			// Confirm Exit Menu
			this.gmConfirmExitMenu = new GMenu( this , 0f , 0f , this.geMain.gcScreenSize.fX , this.geMain.gcScreenSize.fY , 2 , GameSceneStatus.grConfirmExit );
			this.iLoadCnt++;
			
	        GeometryObj goLossAlphaBg = new GeometryObj( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
	        goLossAlphaBg.setGeometry( new GRectangle( this.geMain.gcScreenSize.fX , 0f , 0f , this.geMain.gcScreenSize.fY ) , Color.rgb(255,255,255) , 127 );
	        this.gmConfirmExitMenu.addMenuBg( goLossAlphaBg );
	        this.iLoadCnt++;
	        
			GameObject goLossGrey = new GameObject( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
			goLossGrey.addAnimation( new int[]{ R.drawable.background_grey } );
			this.gmConfirmExitMenu.addMenuBg( goLossGrey );
			this.gmConfirmExitMenu.grBound.set( goLossGrey.grBound );
			this.iLoadCnt++;
			
			this.gmConfirmExitMenu.addNewMenuRow( 1 );
			GameObject txtAreYouSure = new GameObject( this , 0 , GOAnchor.Center );
			txtAreYouSure.addAnimation( new int[]{ R.drawable.txt_areyousure_exit } );
			this.gmConfirmExitMenu.addMenuItem( txtAreYouSure );
			this.iLoadCnt++;
	
			this.gmConfirmExitMenu.addNewMenuRow( 2 );
			ClickableObj btnNot = new ClickableObj( this , 0 , GOAnchor.Center );
			btnNot.addAnimation( new int[]{ R.drawable.btn_not } );
			this.gmConfirmExitMenu.addMenuItem( btnNot );
			this.iLoadCnt++;
			
			
			btnNot.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					confirmExit();
					return null;
				}
			});
			
			ClickableObj btnOk = new ClickableObj( this , 0 , GOAnchor.Center );
			btnOk.addAnimation( new int[]{ R.drawable.btn_ok } );
			this.gmConfirmExitMenu.addMenuItem( btnOk );
			this.iLoadCnt++;
			
			btnOk.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					geMain.isGameEnded = true;
					return null;
				}
			});
			
			this.algmMenuList.add( this.gmConfirmExitMenu );
			this.iLoadCnt++;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.initConfirmExitMenu" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void initConfirmBackMenu() {
		try {
			// Confirm Back Menu
			this.gmConfirmBackMenu = new GMenu( this , 0f , 0f , this.geMain.gcScreenSize.fX , this.geMain.gcScreenSize.fY , 2 , GameSceneStatus.grConfirmBack );
			this.iLoadCnt++;
			
	        GeometryObj goLossAlphaBg = new GeometryObj( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
	        goLossAlphaBg.setGeometry( new GRectangle( this.geMain.gcScreenSize.fX , 0f , 0f , this.geMain.gcScreenSize.fY ) , Color.rgb(255,255,255) , 127 );
	        this.gmConfirmBackMenu.addMenuBg( goLossAlphaBg );
	        this.iLoadCnt++;
	        
			GameObject goLossGrey = new GameObject( this , 0 , GOAnchor.Center , this.geMain.gcScreenSize.fX/2f , this.geMain.gcScreenSize.fY/2f );
			goLossGrey.addAnimation( new int[]{ R.drawable.background_grey } );
			this.gmConfirmBackMenu.addMenuBg( goLossGrey );
			this.gmConfirmBackMenu.grBound.set( goLossGrey.grBound );
			this.iLoadCnt++;
			
			this.gmConfirmBackMenu.addNewMenuRow( 1 );
			GameObject txtAreYouSure = new GameObject( this , 0 , GOAnchor.Center );
			txtAreYouSure.addAnimation( new int[]{ R.drawable.txt_areyousure_backhome } );
			this.gmConfirmBackMenu.addMenuItem( txtAreYouSure );
			this.iLoadCnt++;
	
			this.gmConfirmBackMenu.addNewMenuRow( 2 );
			ClickableObj btnNot = new ClickableObj( this , 0 , GOAnchor.Center );
			btnNot.addAnimation( new int[]{ R.drawable.btn_not } );
			this.gmConfirmBackMenu.addMenuItem( btnNot );
			this.iLoadCnt++;
			
			
			btnNot.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					confirmBackMenu();
					return null;
				}
			});
			
			ClickableObj btnOk = new ClickableObj( this , 0 , GOAnchor.Center );
			btnOk.addAnimation( new int[]{ R.drawable.btn_ok } );
			this.gmConfirmBackMenu.addMenuItem( btnOk );
			this.iLoadCnt++;
			
			btnOk.setBtnClickAct( new ButtonFunction() {
				@Override
				public String[] call() throws Exception {
					goHomePage();
					return null;
				}
			});
			
			this.algmMenuList.add( this.gmConfirmBackMenu );
			this.iLoadCnt++;
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.initConfirmBackMenu" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void preGameLoopLogic() {
		try {
			float fXNewDisp = this.chicken.getXDisplacement();
			float fXDiff = fXNewDisp - this.fLastDisp;
			
			if ( this.toTimer.isTimesUp() ) {
				if ( this.gssStatus != GameSceneStatus.grGameOver ) {
					this.gmLossMenu.showMenu();
				}
			}
			
			if ( this.toStartTimer.isTimesUp() && this.raceNotStart) {
				this.gssStatus = GameSceneStatus.grNormal;
				this.toStartTimer.isShowing = false;
				this.raceNotStart = false;
			}
			
			this.psoStatus.setPlayerProgress( this.sPlayerName , fXNewDisp );
			
			this.gooHandler.setX( fXDiff );
			this.soBackGround.scrollX( -fXDiff );
			
			if ( this.psoStatus.isPlayerFinished( this.sPlayerName ) ) {
				if ( this.gssStatus != GameSceneStatus.grGameWin ) {
					this.gmWinMenu.showMenu();
				}
			}
			
			this.fLastDisp = fXNewDisp;
			
			this.gooHandler.preGameLoopLogic();
			
			super.preGameLoopLogic();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.preGameLoopLogic" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void gameLoopLogic() {
		try {
			this.gooHandler.gameLoopLogic();
			
			super.gameLoopLogic();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.gameLoopLogic" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void postGameLoopLogic() {
		try {
			this.gooHandler.postGameLoopLogic();
			
			super.postGameLoopLogic();
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.postGameLoopLogic" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void backButtonHandler() {
		try {
			switch ( this.gssStatus ) {
			case grNormal:
				this.pause();
				break;
			case grPause:
				this.pause();
				break;
			case grConfirmExit:
				this.confirmExit();
				break;
			default:
				break;
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.backButtonHandler" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void goRewardPage( boolean p_bForce ) {
		boolean bAllowGoNext = p_bForce;
		
		try {
			if ( !this.bIsAnyBTConnectionCreated ) {
				bAllowGoNext = true;
			}
			else if ( this.geMain.gnhHandler.gnbtHandler.bIsServerSide ) {
				this.geMain.gnhHandler.gnbtHandler.pushMsg( new JSONObject().put( "goRewardPage" , "true" ) );
				bAllowGoNext = true;
			}
			
			if ( bAllowGoNext ) {
				synchronized ( this.geMain.shMain ) {
					this.geMain.addToNextScene( new GameReward( this.geMain , new String[] { this.gssStatus.name(), String.valueOf(this.iStage) , String.valueOf(this.iCoins) } ) );
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.goRewardPage" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	public void goHomePage() {
		try {
			synchronized ( this.geMain.shMain ) {
				this.geMain.addToNextScene( new GameHome( this.geMain , null ) );
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.goHomePage" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void pushMsgPre() {
		try {
			if ( this.bIsAnyBTConnectionCreated ) {
				if ( this.geMain.gnhHandler.gnbtHandler.bIsServerSide ) {
					if ( this.joNetwork.length() == 0 ) {
						int cnt = 0;
						
						this.joNetwork.put( "Role" , "Server" );
						this.joNetwork.put( "Server" , this.geMain.gnhHandler.gnbtHandler.getMacAddr() );
						this.joNetwork.put( "Stage" , String.valueOf(this.iStage) );
						this.joNetwork.put( "StageTtl" , String.valueOf(this.fProgressTtl) );
						this.joNetwork.put( "TimeNow" , String.valueOf(this.toTimer.iCntNow) );
						this.joNetwork.put( "Winner" , "" );
						
						JSONObject json2ndLv = new JSONObject();
						json2ndLv.put( "MACAddr" , this.geMain.gnhHandler.gnbtHandler.getMacAddr() );
						json2ndLv.put( "Progress" , String.valueOf(0) );
						cnt++;
						this.joNetwork.put( "P"+String.valueOf(cnt) , json2ndLv );
						
						for ( String btMACAddr : this.geMain.gnhHandler.gnbtHandler.getLinkedMACAddr() ) {
							cnt++;
							json2ndLv = new JSONObject();
							json2ndLv.put( "MACAddr" , btMACAddr );
							json2ndLv.put( "Progress" , String.valueOf(0) );
							this.psoStatus.addPlayer( "P"+String.valueOf(cnt) , this.fProgressTtl );
							
							this.joNetwork.put( "P"+String.valueOf(cnt) , json2ndLv );
						}
						
						this.joNetwork.put( "PlayerCnt" , String.valueOf(cnt) );
					}
				}
				else {
					if ( this.geMain.gnhHandler.gnbtHandler.isConnected() ) {
						if ( this.joNetwork.length() > 0 && this.joNetwork.get( "Winner" ).equals( "" ) ) {
							JSONObject json = new JSONObject();
							
							json.put( "Player" , this.sPlayerName ); 
							json.put( "Progress" , String.valueOf(this.psoStatus.hmPlayer.get(this.sPlayerName).fProgress) );
							
							this.geMain.gnhHandler.gnbtHandler.pushMsg( json );
						}
					}
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.pushMsgPre" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void readMsgPre() {
		JSONObject joMsg;
		String sMsg;
		
		try {
			if ( this.bIsAnyBTConnectionCreated ) {
				if ( this.geMain.gnhHandler.gnbtHandler.bIsServerSide ) {
					for ( String btMACAddr : this.geMain.gnhHandler.gnbtHandler.getLinkedMACAddr() ) {
						sMsg = this.geMain.gnhHandler.gnbtHandler.getMsg( btMACAddr );
						
						if ( sMsg != null && sMsg.length() > 0 ) {
GameUtil.LogMsg( this , "S:" + sMsg );
							joMsg = new JSONObject( sMsg );
							
							if ( joMsg.has( "Player" ) && joMsg.has( "Progress" ) ) {
								this.geMain.gnhHandler.gnbtHandler.pollMsg( btMACAddr );
								this.psoStatus.hmPlayer.get( joMsg.get( "Player" ).toString() ).fProgress = Float.valueOf( joMsg.get( "Progress" ).toString() );
								if ( this.psoStatus.hmPlayer.get( joMsg.get( "Player" ).toString() ).fProgress >= this.fProgressTtl && this.joNetwork.get( "Winner" ).toString().length() == 0 ) {
									this.joNetwork.put( "Winner" , joMsg.get( "Player" ).toString() );
								}
								((JSONObject)this.joNetwork.get( joMsg.get( "Player" ).toString() )).put( "Progress" , this.psoStatus.hmPlayer.get( joMsg.get( "Player" ).toString() ).fProgress );
							}
						}
					}
				}
				else {
					sMsg = this.geMain.gnhHandler.gnbtHandler.getMsg();
					
					if ( sMsg != null && sMsg.length() > 0 ) {
GameUtil.LogMsg( this , "C:" + sMsg );					
						if ( this.joNetwork.length() == 0 ) {
							this.geMain.gnhHandler.gnbtHandler.pollMsg();
							
							this.joNetwork = new JSONObject( sMsg );
							this.joNetwork.put( "Role" , "Client" );
							
							this.iStage = Integer.valueOf( this.joNetwork.get( "Stage" ).toString() );
							this.iTime = Integer.valueOf( this.joNetwork.get( "TimeNow" ).toString() );
							
							this.initGRVar( this.iStage );
							
							for ( int i = 1 ; i <= this.joNetwork.getInt("PlayerCnt") ;  i++ ) {
								if ( ((JSONObject)this.joNetwork.get( "P"+String.valueOf(i) )).get( "MACAddr" ).equals( this.geMain.gnhHandler.gnbtHandler.getMacAddr() ) ) {
									this.sPlayerName = "P"+String.valueOf(i);
									this.psoStatus.hmPlayer.remove("P1");
									this.psoStatus.addPlayer( this.sPlayerName , this.fProgressTtl );
								}
							}
							
							for ( int i = 1 ; i <= this.joNetwork.getInt("PlayerCnt") ;  i++ ) {
								if ( !((JSONObject)this.joNetwork.get( "P"+String.valueOf(i) )).get( "MACAddr" ).equals( this.geMain.gnhHandler.gnbtHandler.getMacAddr() ) ) {
									this.psoStatus.addPlayer( "P"+String.valueOf(i) , this.fProgressTtl );
								}
							}
						}
						else {
							joMsg = new JSONObject( sMsg );
							
							if ( joMsg.has( "goRewardPage" ) && joMsg.get( "goRewardPage" ).equals( "true" ) ) {
								this.geMain.gnhHandler.gnbtHandler.pollMsg();
								this.goRewardPage( true );
							}
						}
					}
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.readMsgPre" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void pushMsgPost() {
		try {
			if ( this.bIsAnyBTConnectionCreated ) {
				if ( this.geMain.gnhHandler.gnbtHandler.bIsServerSide && this.joNetwork.get( "Winner" ).equals( "" ) ) {
					this.joNetwork.put( "TimeNow" , String.valueOf(this.toTimer.iCntNow) );
					((JSONObject)this.joNetwork.get( this.sPlayerName )).put( "Progress" , String.valueOf(this.psoStatus.hmPlayer.get( this.sPlayerName ).fProgress) );
					if ( this.psoStatus.hmPlayer.get( this.sPlayerName ).fProgress >= this.fProgressTtl && this.joNetwork.get( "Winner" ).toString().length() == 0 ) {
						this.joNetwork.put( "Winner" , this.sPlayerName );
					}
					for ( String btMACAddr : this.geMain.gnhHandler.gnbtHandler.getLinkedMACAddr() ) {
						this.geMain.gnhHandler.gnbtHandler.pushMsg( btMACAddr , this.joNetwork );
					}
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.pushMsgPost" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void readMsgPost() {
		String sMsg;
		try {
			if ( this.bIsAnyBTConnectionCreated ) {
				if ( !this.geMain.gnhHandler.gnbtHandler.bIsServerSide ) {
					if ( this.geMain.gnhHandler.gnbtHandler.isConnected() ) {
						sMsg = this.geMain.gnhHandler.gnbtHandler.getMsg();
						if ( sMsg != null && sMsg.length() > 0 ) {
							this.geMain.gnhHandler.gnbtHandler.pollMsg();
							this.joNetwork = new JSONObject( sMsg );
							this.joNetwork.put( "Role" , "Client" );
						}
					}
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.readMsgPost" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
	
	@Override
	public void setVarByNetwork() {
		try {
			if ( this.bIsAnyBTConnectionCreated ) {
				if ( this.joNetwork != null ) {
					if ( this.joNetwork.length() > 0 ) {
						this.toTimer.iCntNow = Integer.valueOf( this.joNetwork.get( "TimeNow" ).toString() );
						
						for ( int i = 1 ; i <= this.joNetwork.getInt("PlayerCnt") ;  i++ ) {
							this.psoStatus.hmPlayer.get( "P"+String.valueOf(i) ).fProgress = Float.valueOf( ((JSONObject)this.joNetwork.get( "P"+String.valueOf(i) )).get( "Progress" ).toString() );
						}
						
						if ( this.joNetwork.get( "Winner" ).toString().length() > 0 ) {
							if ( !this.joNetwork.get( "Winner" ).toString().equals( this.sPlayerName ) ) {
								this.gmLossMenu.showMenu();
							}
						}
						
						this.geMain.gnhHandler.gnbtHandler.pollAllMsg();
					}
				}
			}
		} catch ( Exception p_e ) {
			// TODO Auto-generated catch block
			GameUtil.LogMsg( this , "GameRacing.setVarByNetwork" );
			GameUtil.ErrorHandler( this , p_e );
		}
	}
}
